package  
{
	import flash.display.BitmapData;
	import flash.display.MovieClip;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.utils.Dictionary;
	/**
	 * Contains a vector of all the bitmapdata of the animation.
	 * Also it acts as a movieclip.
	 * @author Lorenzo Nuvoletta
	 */
	public class MovieBMPD
	{		
		public var currentFrame	:int;
		public var scaleX		:Number = 1;
		public var scaleY		:Number = 1;
		
		public var position		:Point;		
		public var totalFrames	:int;
		public var mc:MovieClip;
		
		private var accuratePosition:Point = new Point();
		private var matrix:Matrix;		
		
		private var _rotation	:Number = 0;
		private var _dict		:Dictionary;
		
		
		//GETTERS AND SETTERS
		public function get rotation():Number 
		{
			return _rotation;
		}
		
		public function set rotation(value:Number):void 
		{			
			_rotation = value;
			_rotation = _rotation % 360;
		}
		
		public function MovieBMPD(mc:MovieClip, framesToRender:int = 0) 
		{
			this.mc 		= mc;			
			scaleX   		= mc.scaleX;
			scaleY   		= mc.scaleY;
			rotation 		= mc.rotation;
			position		= new Point(mc.x, mc.y);			
			
			if (framesToRender == 0) {
				framesToRender = mc.totalFrames;
			}
			totalFrames = framesToRender;			
			
			var _existingSpriteSheet:Dictionary = LibraryMovieBMPD.checkExistingClass(mc);
			if (_existingSpriteSheet) {
				_dict = _existingSpriteSheet;
			}
			else {				
				LibraryMovieBMPD.movieBMPDS[LibraryMovieBMPD.getClass(mc)] = _dict = new Dictionary();			
			}			
		}
		
		public function nextFrame():void {
			currentFrame++;
			if (totalFrames <= currentFrame) {
				currentFrame = 0;
			}
		}
		
		public function drawTo(bmpd:BitmapData, cacheNonNormal:Boolean = false ):void {
			var myCustomBMPD:CustomBMPD;
			
			var dStrNormal	:String = getDictString(true);
			var dStr		:String = getDictString(false);
			
			if ( (cacheNonNormal && !_dict[dStr]) || !_dict[dStrNormal] ) {
				if (cacheNonNormal && !_dict[dStr]) {
					_dict[dStr] = new CustomBMPD(this);
					//trace(1, dStr, dStrNormal);
				}
				if (!_dict[dStrNormal]) {
					_dict[dStrNormal] = new CustomBMPD(this, true);
					//trace(2, dStr, dStrNormal);
				}				
			}
			
			if (cacheNonNormal && dStrNormal!=dStr){
				myCustomBMPD = _dict[dStr];
			}
			else {
				myCustomBMPD = _dict[dStrNormal];
			}
			
			accuratePosition.x = position.x + myCustomBMPD.mcRect.x; trace(myCustomBMPD.mcRect.x);
			accuratePosition.y = position.y + myCustomBMPD.mcRect.y;
			
			bmpd.lock();
			if( cacheNonNormal || dStrNormal==dStr){
				bmpd.copyPixels(myCustomBMPD, myCustomBMPD.rect, accuratePosition, null, null, true);
				//trace('copyPixel');
			}
			else {
				if (scaleX < 0) accuratePosition.x -= myCustomBMPD.mcRect.width * scaleX;
				if (scaleY < 0) accuratePosition.y -= myCustomBMPD.mcRect.height * scaleY;
				
				matrix = new Matrix();				
				if(scaleX!=1 || scaleY!=1) matrix.scale(scaleX, scaleY);
				if(rotation) matrix.rotate(rotation*Math.PI/180);
				matrix.translate(accuratePosition.x, accuratePosition.y);				
				bmpd.draw(myCustomBMPD, matrix, null, null, null, true);
				//trace('draw');
			}
			bmpd.unlock();
			
			myCustomBMPD = null;
			matrix = null;
		}
		
		public function getDictString(normal:Boolean = false):String {
			if(normal) return '1.1.0.' + String(currentFrame);
			else return String(scaleX) + '.' + String(scaleY) + '.' + String(rotation) + '.' + String(currentFrame);
		}		
		
	}

}